From [Baker-Luecke] we get a whole infinite family of asymmetric L-space knots that all admit at least one alternating surgery. In this notebook we work with this infinite family. First we build the 14 simplest of these knost and then demonstrate that they al have exactly two dbc slopes.
# The relevant code.
import snappy
import time
def torsion_coef(knot):
'''
A function that takes the name of a knot and return the torsion coefficients of its normalized Alexander polynomial.
'''
M=snappy.Manifold(knot)
a=M.alexander_polynomial().list()
t=[]
for i in range(0,len(a)):
ti=0
for j in range(0,len(a)-i):
ti=ti+j*a[j+i]
t.append(ti)
# Next we need to adjust for the correct normalization of the Alexander polynomial
g=int((len(t)-1)/2)
r=t[g:2*g]
T=[]
Ti=0
for i in range(1,r[0]+1):
Ti=r.count(i)+Ti
T.append(Ti)
return T
## This code calculates the stable coefficients given the torsion
## coefficients. If no stable coefficients can exist it will return False.
## It takes as input the list [T_1, \dots, T_{t0}]. Where T_k is defined
## as the number if 0\leq i <g such that t_i\leq k.
def Generate_S(n):
##Generate the tuples S_k for k=0 to n.
S=[]
for k in range(0,n+1):
S+=[[]]
j=1
while j*(j+1)<2*k:
for t in S[k-(j*(j+1))//2]:
if j>=t[0]:
S[k]+=[[j]+t]
j+=1
if j*(j+1)==2*k:
S[k]+=[[j]]
return S
def max_pairing(sigma, Sk):
##compute max \sigma \cdot \alpha for all \alpha in Sk
prodlist = [sum([z[0]*z[1] for z in zip(alpha, sigma)]) for alpha in Sk]
return max(prodlist)
def Calc_Stable(Tlist):
##Take the tuple of T_i and determine whether there exists a
##tuple of stable coefficients consistent with this.
t0=len(Tlist)
g=Tlist[-1]
##For indexing reasons append a 0 to the start.
T=[0]+Tlist
rho=[]
S=Generate_S(t0)
k=1
##Calculate the \rho_i greater than 2.
while k<=t0 and T[k]-T[k-1]>2:
if max_pairing(rho,S[k])<T[k]:
rho+=[T[k]-T[k-1]]
##Check rho decreasing
if k>1 and rho[-1]>rho[-2]:
return False
k+=1
##Fill out rho with 2s.
gsum=sum([(x*(x-1))//2 for x in rho])
if gsum>g:
return False
rho+=[2]*(g-gsum)
##Finally check that rho is compatible with the T we started with.
##pad out rho with some entries equal to one and compute the
##relevant maxima.
sigma=rho+[1]*t0
for k in range(1,t0):
if T[k]!=max_pairing(sigma,S[k]):
return False
if max_pairing(sigma,S[t0])<g:
return False
return rho
def compute_N(stable_coefficients):
'''
Takes as input the stable coefficients and returns the integer N.
'''
N=0
stable_coefficients=sorted(stable_coefficients)
for s in stable_coefficients:
N=N+s*s
values=[]
for s in stable_coefficients:
value=s
for x in stable_coefficients[0:stable_coefficients.index(s)]:
value=value-x
values.append(value)
return N+max(values)
def all_positive(manifold):
'''
Checks if the solution type of a triangulation is positive.
'''
return manifold.solution_type() == 'all tetrahedra positively oriented'
def find_positive_triangulations(manifold,number=1,tries=100):
'''
Searches for one triangulation with a positive solution type.
(Or if number is set to a different value also for different such triangulations.)
'''
M = manifold.copy()
pos_triangulations=[]
for i in range(tries):
if all_positive(M):
pos_triangulations.append(M)
if len(pos_triangulations)==number:
return pos_triangulations
break
M.randomize()
for d in M.dual_curves(max_segments=500):
X = M.drill(d)
X = X.filled_triangulation()
X.dehn_fill((1,0),-1)
for i in range(tries):
if all_positive(X):
pos_triangulations.append(X)
if len(pos_triangulations)==number:
return pos_triangulations
break
X.randomize()
# In the closed case, here is another trick.
if all(not c for c in M.cusp_info('is_complete')):
for i in range(tries):
# Drills out a random edge
X = M.__class__(M.filled_triangulation())
if all_positive(X):
pos_triangulations.append(X)
if len(pos_triangulations)==number:
return pos_triangulations
break
M.randomize()
return pos_triangulations
def better_symmetry_group(M,index=100,num_pos_triang=1):
'''
This function computes the symmetry group of the input manifold.
If the second entry is True it is proven to be the symmetry group.
'''
full=False
S='unclear'
try:
S=M.symmetry_group()
full=S.is_full_group()
if full:
return (S,full)
except (ValueError, RuntimeError, snappy.SnapPeaFatalError):
pass
pos_triang=find_positive_triangulations(M,tries=index,number=num_pos_triang)
if pos_triang==[]:
randomizeCount=0
while randomizeCount<index and full==False:
try:
S=M.symmetry_group()
full=S.is_full_group()
if full:
return (S,full)
M.randomize()
randomizeCount=randomizeCount+1
except (ValueError, RuntimeError, snappy.SnapPeaFatalError):
M.randomize()
randomizeCount=randomizeCount+1
for X in pos_triang:
randomizeCount=0
while randomizeCount<index and full==False:
try:
S=X.symmetry_group()
full=S.is_full_group()
if full:
return (S,full)
X.randomize()
randomizeCount=randomizeCount+1
except (ValueError, RuntimeError, snappy.SnapPeaFatalError):
X.randomize()
randomizeCount=randomizeCount+1
return (S,full)
def better_verify_hyperbolicity(K,index=10):
pos_triang=find_positive_triangulations(K,tries=index)
for X in pos_triang:
try:
w=X.verify_hyperbolicity()[0]
if w:
return w
except RuntimeError:
pass
return False
L=snappy.Manifold('NewSurgLinkReducedReduced.txt')
index_set=[[1,1,1,1,0],[1,1,0,1,1],[1,1,1,2,0],[1,1,2,1,0],[1,2,1,1,0],[2,1,1,1,0],[1,1,1,1,1],[1,1,0,2,1],[1,2,0,1,1],[1,1,2,2,0],[1,2,1,2,0],[2,1,1,2,0],[1,1,0,1,2],[2,1,0,1,1]]
knots=[]
for (m,b1,a1,a2,a3) in index_set:
p=a1*a2*a3+a1+a3;
q=a2*a3+1;
L.dehn_fill([(p,q),(m,1),(1,1),(-1,1),(1,1),(-1,1),(-1-a1,1),(-a3,1),(1,1),(1,m),(a2,1),(1,b1),(0,0),(-1,b1)]);
K=L.filled_triangulation(); #useful to get snappy to find the hyp structure
K.set_peripheral_curves( [ (-1,0), K.homological_longitude() ] , 0) #set meridians and longitude right
K.set_name('BL_knot:'+str([m,b1,a1,a2,a3]))
K.simplify()
knots.append(K)
knots
[BL_knot:[1, 1, 1, 1, 0](0,0), BL_knot:[1, 1, 0, 1, 1](0,0), BL_knot:[1, 1, 1, 2, 0](0,0), BL_knot:[1, 1, 2, 1, 0](0,0), BL_knot:[1, 2, 1, 1, 0](0,0), BL_knot:[2, 1, 1, 1, 0](0,0), BL_knot:[1, 1, 1, 1, 1](0,0), BL_knot:[1, 1, 0, 2, 1](0,0), BL_knot:[1, 2, 0, 1, 1](0,0), BL_knot:[1, 1, 2, 2, 0](0,0), BL_knot:[1, 2, 1, 2, 0](0,0), BL_knot:[2, 1, 1, 2, 0](0,0), BL_knot:[1, 1, 0, 1, 2](0,0), BL_knot:[2, 1, 0, 1, 1](0,0)]
These are the first 14 knots from [Baker-Lucke]. We will first verify that these are aymmetric hyperbolic knots.
start_time = time.time()
for K in knots:
print(K)
print('The knot is hyperbolic:',better_verify_hyperbolicity(K))
print('Symmetry group:',better_symmetry_group(K))
print('-----------------------')
print("--- Time taken: %s seconds ---" % ((time.time() - start_time)))
BL_knot:[1, 1, 1, 1, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 0, 1, 1](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 1, 2, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 2, 1, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 2, 1, 1, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[2, 1, 1, 1, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 1, 1, 1](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 0, 2, 1](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 2, 0, 1, 1](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 2, 2, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 2, 1, 2, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[2, 1, 1, 2, 0](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[1, 1, 0, 1, 2](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- BL_knot:[2, 1, 0, 1, 1](0,0) The knot is hyperbolic: True Symmetry group: (0, True) ----------------------- --- Time taken: 3.818368911743164 seconds ---
Next, we calculate the stable coefficient and from that we determine the unit interval that contains all alternating slopes.
start_time = time.time()
stable_coefficients=[]
possible_alternating_int_slopes=[]
for K in knots:
T=torsion_coef(K)
s_coef=Calc_Stable(T)
stable_coefficients.append([K.name(),s_coef])
N=compute_N(s_coef)
print('Knot:',K.name())
print('Stable coefficients:',s_coef)
print('Possible integer alternating slopes:',N-1,N,N+1)
possible_alternating_int_slopes.append([K,(N-1,1),(N,1),(N+1,1)])
print('-------------')
print("--- Total time taken: %s Minutes ---" % ((time.time() - start_time)/60))
Knot: BL_knot:[1, 1, 1, 1, 0] Stable coefficients: [12, 9, 5, 4, 2] Possible integer alternating slopes: 271 272 273 ------------- Knot: BL_knot:[1, 1, 0, 1, 1] Stable coefficients: [16, 12, 7, 4, 2] Possible integer alternating slopes: 470 471 472 ------------- Knot: BL_knot:[1, 1, 1, 2, 0] Stable coefficients: [12, 12, 9, 5, 4, 2] Possible integer alternating slopes: 415 416 417 ------------- Knot: BL_knot:[1, 1, 2, 1, 0] Stable coefficients: [17, 14, 5, 5, 4, 2] Possible integer alternating slopes: 556 557 558 ------------- Knot: BL_knot:[1, 2, 1, 1, 0] Stable coefficients: [17, 13, 7, 6, 3] Possible integer alternating slopes: 554 555 556 ------------- Knot: BL_knot:[2, 1, 1, 1, 0] Stable coefficients: [18, 13, 7, 6, 2, 2] Possible integer alternating slopes: 587 588 589 ------------- Knot: BL_knot:[1, 1, 1, 1, 1] Stable coefficients: [26, 17, 12, 5, 4, 2] Possible integer alternating slopes: 1155 1156 1157 ------------- Knot: BL_knot:[1, 1, 0, 2, 1] Stable coefficients: [23, 19, 7, 7, 4, 2] Possible integer alternating slopes: 1009 1010 1011 ------------- Knot: BL_knot:[1, 2, 0, 1, 1] Stable coefficients: [23, 17, 10, 6, 3] Possible integer alternating slopes: 965 966 967 ------------- Knot: BL_knot:[1, 1, 2, 2, 0] Stable coefficients: [17, 17, 14, 5, 5, 4, 2] Possible integer alternating slopes: 845 846 847 ------------- Knot: BL_knot:[1, 2, 1, 2, 0] Stable coefficients: [17, 17, 13, 7, 6, 3] Possible integer alternating slopes: 843 844 845 ------------- Knot: BL_knot:[2, 1, 1, 2, 0] Stable coefficients: [18, 18, 13, 7, 6, 2, 2] Possible integer alternating slopes: 911 912 913 ------------- Knot: BL_knot:[1, 1, 0, 1, 2] Stable coefficients: [28, 12, 12, 7, 4, 2] Possible integer alternating slopes: 1142 1143 1144 ------------- Knot: BL_knot:[2, 1, 0, 1, 1] Stable coefficients: [24, 18, 11, 6, 2, 2] Possible integer alternating slopes: 1066 1067 1068 ------------- --- Total time taken: 1.1201301693916321 Minutes ---
stable_coefficients
[['BL_knot:[1, 1, 1, 1, 0]', [12, 9, 5, 4, 2]], ['BL_knot:[1, 1, 0, 1, 1]', [16, 12, 7, 4, 2]], ['BL_knot:[1, 1, 1, 2, 0]', [12, 12, 9, 5, 4, 2]], ['BL_knot:[1, 1, 2, 1, 0]', [17, 14, 5, 5, 4, 2]], ['BL_knot:[1, 2, 1, 1, 0]', [17, 13, 7, 6, 3]], ['BL_knot:[2, 1, 1, 1, 0]', [18, 13, 7, 6, 2, 2]], ['BL_knot:[1, 1, 1, 1, 1]', [26, 17, 12, 5, 4, 2]], ['BL_knot:[1, 1, 0, 2, 1]', [23, 19, 7, 7, 4, 2]], ['BL_knot:[1, 2, 0, 1, 1]', [23, 17, 10, 6, 3]], ['BL_knot:[1, 1, 2, 2, 0]', [17, 17, 14, 5, 5, 4, 2]], ['BL_knot:[1, 2, 1, 2, 0]', [17, 17, 13, 7, 6, 3]], ['BL_knot:[2, 1, 1, 2, 0]', [18, 18, 13, 7, 6, 2, 2]], ['BL_knot:[1, 1, 0, 1, 2]', [28, 12, 12, 7, 4, 2]], ['BL_knot:[2, 1, 0, 1, 1]', [24, 18, 11, 6, 2, 2]]]
From the OSB notebook it follows that only N-1 and N admit OSBs. And from the Goeritz matrices or by running a brute force search we get explicit branching sets as shown in the table in our paper.